package com.wmh.baseservice.common.shiro.config;

import com.wmh.baseservice.common.shiro.realm.JwtRealm;
import com.wmh.baseservice.common.shiro.service.JwtShiroFilter;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.mgt.SubjectFactory;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;


/**
 * @author xy
 * @Date: 2021-10-28 15:23
 * @describe shiro常规配置类
 */
@Configuration
public class ShiroConfig {

    public static final String SHIRO_ADMIN = "shiro:admin";
    public static final String SHIRO_USER = "shiro:user";
    public static final String SHIRO_MERCHANT = "shiro:merchant";
    public static final String SHIRO_SSO = "shiro:sso";

    /**
     * 不使用默认的DefaultSubject创建对象，因为不能创建Session
     * */
    @Bean
    public SubjectFactory subjectFactory() {
        return new JwtDefaultSubjectFactory();
    }

    @Bean
    public Realm realm() {
        JwtRealm jwtRealm = new JwtRealm();
        jwtRealm.setCredentialsMatcher(passwordMatcher());
        return jwtRealm;
    }

    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        /*
         * b
         * */
        // 关闭 ShiroDAO 功能
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        // 不需要将 Shiro Session 中的东西存到任何地方（包括 Http Session 中）
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        securityManager.setSubjectDAO(subjectDAO);
        //禁止Subject的getSession方法
        securityManager.setSubjectFactory(subjectFactory());
        securityManager.setRealm(realm());
        return securityManager;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean() {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager());
        /*
         *  添加jwt过滤器，并在下面注册
         * 也就是将jwtFilter注册到shiro的Filter中
         * 指定除了login和logout之外的请求都先经过jwtFilter
         * */
        Map<String, Filter> filterMap = new HashMap<>();
        filterMap.put("jwt", new JwtShiroFilter());
        shiroFilter.setFilters(filterMap);
        // 拦截器
        Map<String, String> filterRuleMap = new LinkedHashMap<>();
        //放行swagger
        filterRuleMap.put("/swagger-ui.html", "anon");
        filterRuleMap.put("/swagger-resources", "anon");
        filterRuleMap.put("/v3/api-docs", "anon");
        filterRuleMap.put("/doc.html", "anon");
        filterRuleMap.put("/webjars/**", "anon");
        filterRuleMap.put("/static/**", "anon");
        filterRuleMap.put("/files/**", "anon");
        filterRuleMap.put("/favicon.ico","anon");
        //公共接口建议全部分出一个controller，公开的方法都写在里面
        filterRuleMap.put("/**/public/**", "anon");
        filterRuleMap.put("/**/websocket/**", "anon");
        filterRuleMap.put("/**", "jwt");
        shiroFilter.setFilterChainDefinitionMap(filterRuleMap);
        return shiroFilter;
    }

    @Bean
    public PasswordMatcher passwordMatcher() {
        //自定义的密码比较器
        return new PasswordMatcher();
    }

    @Bean
    public HashedCredentialsMatcher getHashedCredentialsMatcher() {
        //原有默认的不再使用
        HashedCredentialsMatcher rm = new HashedCredentialsMatcher();
        rm.setHashAlgorithmName("md5");
        rm.setHashIterations(1);
        return rm;
    }

    /**
     * 开启aop注解支持
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }


}
